home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 8
/
Aminet 8 (1995)(GTI - Schatztruhe)[!][Oct 1995].iso
/
Aminet
/
comm
/
tcp
/
netinput37_3.lha
/
NetInput
/
source
/
netinput.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-07-24
|
12KB
|
464 lines
/*
** $VER: netinput.c 1.3 (22 Jul 1995)
**
** AMIGA netinput client code
**
** (C (14 Jul 1995) Copyright 1995 Marius Gröger
** All Rights Reserved
**
** $HISTORY:
**
** 22 Jul 1995 : 001.003 : QUIET option
** 14 Jul 1995 : 001.002 : some code cleanup
** 06 Mar 1995 : 001.001 : version id added
** 05 Mar 1995 : 001.000 : created
*/
#define DEBUG 0
/*F*/ /* includes */
#include <NETINCLUDE:sys/types.h>
#include <NETINCLUDE:sys/stat.h>
#include <NETINCLUDE:stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <clib/netlib_protos.h>
#include <netdb.h>
#include <clib/dos_protos.h>
#include <pragmas/dos_pragmas.h>
#include <clib/exec_protos.h>
#include <pragmas/exec_sysbase_pragmas.h>
#include <exec/memory.h>
#include <exec/io.h>
#include <exec/interrupts.h>
#include <devices/input.h>
#include <devices/inputevent.h>
#include "netinput.h"
#include "unixsem.h"
#include "compiler.h"
#include "debug.h"
/*E*/
/*F*/ /* global data */
extern struct Library *SocketBase, *DOSBase;
#define TEMPLATE "HOST/A,IMM=IGNOREMOUSEMOVES/K/N,QUIET/S"
enum { ARG_HOST, ARG_IMM, ARG_QUIET, ARG_COUNT };
#define MAX_IMM 900000
#define MIN_IMM 0
#define DEF_IMM 0
/*
** we maintain an InputEvent-FIFO of FIFO_COUNT elements
** this value MUST be power of 2!
*/
#define FIFO_COUNT 64
typedef struct GlobalData
{
struct Library *gd_SysBase,
*gd_UtilityBase,
*gd_DOSBase;
struct MsgPort *gd_IPort;
struct IOStdReq *gd_IReq;
struct Interrupt gd_InputHandler;
UBYTE gd_ProgramName[100];
UBYTE gd_HostName[64];
ULONG gd_Flags;
int gd_Socket;
CountSemaphore gd_Full,
gd_Empty;
struct InputEvent gd_Event[FIFO_COUNT],
gd_Intermediate;
UWORD gd_Write, gd_Read;
struct Task *gd_We;
LONG gd_IgnoreMouseMoves;
int gd_Quiet : 1;
} *GD;
#define FOGF_HANDLER_INSTALLED (1<<0)
#ifdef __SASC
/*
** redirect all shared library bases to our device base.
*/
# define SysBase gd->gd_SysBase
# define DOSBase gd->gd_DOSBase
# define UtilityBase gd->gd_UtilityBase
/*
** This macro declares a local variable which temporary gets
** SysBase directly from AbsExecBase.
*/
# define LOCALSYSBASE struct { void *gd_SysBase; } *gd = (void*)0x4
#else
# error Please define library bases for your compiler
#endif
/*E*/
/*F*/ /* revision */
#define VERSION 37
#define REVISION 1
#define DATE "22.07.95"
#define VERS "netinputd 37.1"
#define VSTRING "netinputd 37.1 (22.07.95)"
#define VERSTAG "\0$VER: netinputd 37.1 (22.07.95)"
const STATIC UBYTE version[]=VERSTAG;
/*E*/
/*F*/ /* private symbols */
static int init_client(char *hostname, char *servername, char *protocolname, char *yourname);
static BOOL parseargs(GD gd);
static VOID freeall(GD gd);
static BOOL openall(GD gd);
static GD creategd(VOID);
static BOOL request(GD gd, ULONG type, ULONG flags);
static ASM SAVEDS struct InputEvent *inputhandler(REG(a0) struct InputEvent *event, REG(a1) GD gd);
static VOID removehandler(GD gd);
static BOOL installhandler(GD gd);
/*E*/
/*F*/ /* exported symbols */
extern VOID main(VOID);
/*E*/
/*F*/ static int init_client(char *hostname, char *servername, char *protocolname, char *yourname)
{
int sock = -1;
struct servent *sp;
struct hostent *hp;
struct sockaddr_in server;
sp = getservbyname(servername, protocolname);
if (sp != NULL)
{
hp = gethostbyname(hostname);
if (hp != NULL)
{
bzero((char *)&server, sizeof(server));
server.sin_port = sp->s_port;
bcopy(hp->h_addr, (char *)&server.sin_addr, hp->h_length);
server.sin_family = hp->h_addrtype;
sock = socket(AF_INET, (LONG)(strcmp(protocolname,"tcp") ? SOCK_DGRAM : SOCK_STREAM), 0);
if (sock >= 0)
{
if (connect((LONG)sock, (struct sockaddr *)&server, sizeof (server)) < 0)
{
close(sock);
sock = -1;
}
}
}
}
return sock;
}
/*E*/
/*F*/ static BOOL parseargs(GD gd)
{
struct RDArgs *rda;
BOOL rc = FALSE;
LONG param[ARG_COUNT];
memset(param, 0, sizeof(param));
if (rda = ReadArgs(TEMPLATE, param, NULL))
{
strncpy(gd->gd_HostName, (char*)param[ARG_HOST], sizeof(gd->gd_HostName)-1);
gd->gd_IgnoreMouseMoves = DEF_IMM;
if (param[ARG_IMM])
{
gd->gd_IgnoreMouseMoves = *((LONG*)param[ARG_IMM]);
if (gd->gd_IgnoreMouseMoves > MAX_IMM) gd->gd_IgnoreMouseMoves = MAX_IMM;
else if (gd->gd_IgnoreMouseMoves < MIN_IMM) gd->gd_IgnoreMouseMoves = MIN_IMM;
}
d(("hostname %s, imm %ld\n",gd->gd_HostName, gd->gd_IgnoreMouseMoves));
gd->gd_Quiet = (param[ARG_QUIET] != 0);
rc = TRUE;
FreeArgs(rda);
}
else PrintFault(IoErr(), gd->gd_ProgramName);
return(rc);
}
/*E*/
/*F*/ static VOID removehandler(GD gd)
{
if (gd->gd_Flags & FOGF_HANDLER_INSTALLED)
{
gd->gd_IReq->io_Command = IND_REMHANDLER;
gd->gd_IReq->io_Data = (APTR)&gd->gd_InputHandler;
gd->gd_IReq->io_Length = sizeof(struct Interrupt);
if (!DoIO((struct IORequest*)gd->gd_IReq))
gd->gd_Flags &= ~FOGF_HANDLER_INSTALLED;
}
}
/*E*/
/*F*/ static BOOL installhandler(GD gd)
{
BOOL rv = FALSE;
gd->gd_InputHandler.is_Code = (void (*)())&inputhandler;
gd->gd_InputHandler.is_Data = (APTR)gd;
gd->gd_InputHandler.is_Node.ln_Pri = 127;
gd->gd_InputHandler.is_Node.ln_Type = NT_UNKNOWN;
gd->gd_InputHandler.is_Node.ln_Name = "« netinput »";
gd->gd_IReq->io_Command = IND_ADDHANDLER;
gd->gd_IReq->io_Data = (APTR)&gd->gd_InputHandler;
gd->gd_IReq->io_Length = sizeof(struct Interrupt);
if (!DoIO((struct IORequest*)gd->gd_IReq))
{
gd->gd_Flags |= FOGF_HANDLER_INSTALLED;
rv = TRUE;
}
return rv;
}
/*E*/
/*F*/ static VOID freeall(GD gd)
{
if (gd->gd_IReq)
{
if (gd->gd_IReq->io_Device) CloseDevice((struct IORequest*)gd->gd_IReq);
DeleteIORequest(gd->gd_IReq);
}
if (gd->gd_IPort) DeleteMsgPort(gd->gd_IPort);
if (DOSBase) CloseLibrary(DOSBase);
if (UtilityBase) CloseLibrary(UtilityBase);
FreeVec(gd);
}
/*E*/
/*F*/ static BOOL openall(GD gd)
{
BOOL rv = FALSE;
sinit(&gd->gd_Full,-1);
sinit(&gd->gd_Empty,-1);
sset(&gd->gd_Full, 0);
sset(&gd->gd_Empty, FIFO_COUNT);
gd->gd_Read = 0;
gd->gd_Write = 0;
gd->gd_We = FindTask(NULL);
d(("opening dos.library\n"))
if (DOSBase = OpenLibrary("dos.library", 37))
{
d(("opening utility.library\n"))
if (UtilityBase = OpenLibrary("utility.library", 37))
{
d(("creating msg port\n"))
if (gd->gd_IPort = CreateMsgPort())
{
d(("creating io request\n"))
if (gd->gd_IReq = CreateIORequest(gd->gd_IPort, sizeof(struct IOStdReq)))
{
d(("opening input.device\n"))
if (!OpenDevice("input.device",0,(struct IORequest*)gd->gd_IReq, 0))
{
rv = TRUE;
}
}
}
}
}
return rv;
}
/*E*/
/*F*/ static GD creategd(VOID)
{
GD new;
LOCALSYSBASE;
new = AllocVec(sizeof(struct GlobalData), MEMF_ANY | MEMF_CLEAR);
new->gd_SysBase = SysBase;
return new;
}
/*E*/
/*F*/ static VOID INLINE forwardevent(GD gd, struct InputEvent *event)
{
swait(&gd->gd_Empty);
gd->gd_Event[gd->gd_Write] = *event;
ssignal(&gd->gd_Full);
gd->gd_Write = (gd->gd_Write+1) & (FIFO_COUNT-1);
}
/*E*/
/*F*/ static ASM SAVEDS struct InputEvent *inputhandler(REG(a0) struct InputEvent *event, REG(a1) GD gd)
{
switch(event->ie_Class)
{
case IECLASS_RAWMOUSE:
if ((event->ie_Code & 0xFF) != IECODE_NOBUTTON)
{
if (gd->gd_Intermediate.ie_Class != IECLASS_NULL)
{
d(("writing event 3\n"));
forwardevent(gd, &gd->gd_Intermediate);
gd->gd_Intermediate.ie_Class = IECLASS_NULL;
}
forwardevent(gd, event);
}
else if (gd->gd_IgnoreMouseMoves)
{
if (gd->gd_Intermediate.ie_Class != IECLASS_NULL)
{
d (("%ld/%ld - %ld/%ld\n",event->ie_TimeStamp.tv_secs,
event->ie_TimeStamp.tv_micro,
gd->gd_Intermediate.ie_TimeStamp.tv_secs,
gd->gd_Intermediate.ie_TimeStamp.tv_micro));
if ((event->ie_TimeStamp.tv_secs == gd->gd_Intermediate.ie_TimeStamp.tv_secs) &&
((event->ie_TimeStamp.tv_micro - gd->gd_Intermediate.ie_TimeStamp.tv_micro) <= gd->gd_IgnoreMouseMoves))
{
d(("storing event 1\n"));
gd->gd_Intermediate = *event;
}
else
{
d(("writing event 1\n"));
gd->gd_Intermediate.ie_Class = IECLASS_NULL;
forwardevent(gd, event);
}
}
else
{
d(("storing event 2\n"));
gd->gd_Intermediate = *event;
}
}
else
{
d(("writing event 2\n"));
forwardevent(gd, event);
}
event = NULL;
break;
case IECLASS_RAWKEY:
if (gd->gd_Intermediate.ie_Class != IECLASS_NULL)
{
forwardevent(gd, &gd->gd_Intermediate);
gd->gd_Intermediate.ie_Class = IECLASS_NULL;
}
if (((event->ie_Code & ~IECODE_UP_PREFIX) == 0x45) && (event->ie_Qualifier & IEQUALIFIER_CONTROL))
{
if (event->ie_Code & IECODE_UP_PREFIX)
Signal(gd->gd_We, SIGBREAKF_CTRL_C);
event = NULL;
break;
}
forwardevent(gd,event);
event = NULL;
break;
default:
if (gd->gd_Intermediate.ie_Class != IECLASS_NULL)
{
forwardevent(gd, &gd->gd_Intermediate);
gd->gd_Intermediate.ie_Class = IECLASS_NULL;
}
break;
}
return event;
}
/*E*/
/*F*/ static BOOL request(GD gd, ULONG type, ULONG flags)
{
int l;
struct foPacket foc;
foc.Type = type;
foc.Flags = flags;
l = send((LONG)gd->gd_Socket, (UBYTE*)&foc, sizeof(foc), 0);
return (BOOL)(l == sizeof(foc));
}
/*E*/
/*F*/ extern VOID main(VOID)
{
int rc = RETURN_FAIL;
GD gd;
if (gd = creategd())
{
d(("gd at %lx\n",gd))
if (openall(gd))
{
GetProgramName(gd->gd_ProgramName, sizeof(gd->gd_ProgramName));
if (parseargs(gd))
{
gd->gd_Socket = init_client(gd->gd_HostName, FO_SERVERNAME, FO_PROTOCOL, gd->gd_ProgramName);
if (gd->gd_Socket >= 0)
{
if (installhandler(gd))
{
if (!gd->gd_Quiet)
Printf( "Transparent mode on.\nEscape key is <Ctrl-Escape>.\n");
while(!(SetSignal(0,0) & SIGBREAKF_CTRL_C))
{
swait(&gd->gd_Full);
if (request(gd, FOPT_Event, 0))
{
send((LONG)gd->gd_Socket, (UBYTE*)&gd->gd_Event[gd->gd_Read], sizeof(struct InputEvent), 0);
}
ssignal(&gd->gd_Empty);
gd->gd_Read = (gd->gd_Read+1) & (FIFO_COUNT-1);
}
if (!gd->gd_Quiet)
Printf( "Transparent mode left.\n");
removehandler(gd);
rc = TRUE;
}
if (!request(gd, FOPT_Finish, 0))
Printf( "%s: could not finish connection\n", gd->gd_ProgramName);
else
rc = RETURN_OK;
}
shutdown(gd->gd_Socket,2);
close(gd->gd_Socket);
}
}
freeall(gd);
}
exit(rc);
}
/*E*/